package com.fs.mybatis.service;

import java.io.File;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;

import org.springframework.stereotype.Service;

import com.fs.mybatis.core.api.GeneratedJavaFile;
import com.fs.mybatis.core.api.GeneratedXmlFile;
import com.fs.mybatis.core.api.IntrospectedTable;
import com.fs.mybatis.core.api.JavaTypeResolver;
import com.fs.mybatis.core.generator.config.Context;
import com.fs.mybatis.core.generator.exception.ShellException;
import com.fs.mybatis.core.generator.internal.ObjectFactory;
import com.fs.mybatis.core.generator.internal.db.DatabaseIntrospector;
import com.fs.mybatis.domain.Table;

@Service
public class CodeServiceImpl extends GeneralCodeService implements CodeService {

    public List<Table> getTargetDatabaseTables(String url, String usr, String pas) throws ClassNotFoundException,
            SQLException {
        String db = getDatabaseType(url);
        if (db.equals("oracle")) {
            return getOracleTables(url, usr, pas);
        } else if (db.equals("mysql")) {
            return getMysqlTables(url, usr, pas);
        }
        return null;
    }

    public Map<File, String> readWriteFiles(Context context) {
        return null;
    }

    public Map<File, String> generalFiles(Context context) {
        Map<File, String> files = new HashMap<File, String>();
        IntrospectedTable introspectedTable = getIntrospectedTables(context);
        if (introspectedTable != null) {
            introspectedTable.initialize();
            introspectedTable.calculateGenerators();
        }
        List<GeneratedJavaFile> generatedJavaFiles = generatedJavaFiles(introspectedTable);
        List<GeneratedXmlFile> generatedXmlFiles = generatedXmlFiles(introspectedTable);

        Set<String> projects = new HashSet<String>();
        for (GeneratedXmlFile gxf : generatedXmlFiles) {
            projects.add(gxf.getTargetProject());
            File targetFile;
            String source;
            try {
                File directory = getDirectory(gxf.getTargetProject(), gxf.getTargetPackage());
                targetFile = new File(directory, gxf.getFileName());
                source = gxf.getFormattedContent();
            } catch (ShellException e) {
                e.printStackTrace();
                continue;
            }
            files.put(targetFile, source);
        }

        for (GeneratedJavaFile gjf : generatedJavaFiles) {
            projects.add(gjf.getTargetProject());
            File targetFile;
            String source;
            try {
                File directory = getDirectory(gjf.getTargetProject(), gjf.getTargetPackage());
                targetFile = new File(directory, gjf.getFileName());
                source = gjf.getFormattedContent();
                files.put(targetFile, source);
            } catch (ShellException e) {
                e.printStackTrace();
            }
        }
        return files;
    }

    private IntrospectedTable getIntrospectedTables(Context context) {
        IntrospectedTable table = null;
        JavaTypeResolver javaTypeResolver = ObjectFactory.createJavaTypeResolver(context);
        Connection connection = null;
        try {
            connection = getConnection(context.getJdbcConnectionConfiguration());
            DatabaseIntrospector databaseIntrospector =
                    new DatabaseIntrospector(context, connection.getMetaData(), javaTypeResolver);
            table = databaseIntrospector.introspectTables(context.getTabconfig());
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            closeConnection(connection);
        }
        return table;
    }

    private List<GeneratedJavaFile> generatedJavaFiles(IntrospectedTable introspectedTable) {
        List<GeneratedJavaFile> generatedJavaFiles = new ArrayList<GeneratedJavaFile>();
        generatedJavaFiles = introspectedTable.getGeneratedJavaFiles();
        return generatedJavaFiles;
    }
    
    private List<GeneratedXmlFile> generatedXmlFiles(IntrospectedTable introspectedTable) {
        List<GeneratedXmlFile> generatedXmlFiles = new ArrayList<GeneratedXmlFile>();
        generatedXmlFiles = introspectedTable.getGeneratedXmlFiles();
        return generatedXmlFiles;
    }

    private List<GeneratedXmlFile> readWriteXmlFiles() {
        List<GeneratedXmlFile> generatedXmlFiles = new ArrayList<GeneratedXmlFile>();

        return generatedXmlFiles;
    }
    private List<GeneratedJavaFile> readWriteJavaFiles() {
        List<GeneratedJavaFile> generatedJavaFiles = new ArrayList<GeneratedJavaFile>();

        return generatedJavaFiles;
    }

    protected File getDirectory(String targetProject, String targetPackage) throws ShellException {
        File project = new File(targetProject);
        if (!project.isDirectory()) {
            project.mkdir();
        }
        StringBuilder sb = new StringBuilder();
        StringTokenizer st = new StringTokenizer(targetPackage, "."); //$NON-NLS-1$
        while (st.hasMoreTokens()) {
            sb.append(st.nextToken());
            sb.append(File.separatorChar);
        }

        File directory = new File(project, sb.toString());
        if (!directory.isDirectory()) {
            boolean rc = directory.mkdirs();
            if (!rc) {
                throw new ShellException("创建失败" + project);
            }
        }

        return directory;
    }

}
